//
// Created by LiuYou on 2021/8/7.
//

#include <pthread.h>
#include <sys/syslog.h>
#include <cstring>
#include <cstdlib>
#include <cerrno>
#include <netinet/in.h>
#include <unistd.h>
#include "ThreadList.hpp"
#include "../include/NetRadioType.hpp"
#include "../include/Protocol.hpp"
#include "MediaLib.hpp"
#include "Server.hpp"


// TODO 注意: !!! using声明的位置编写在哪里？
using NetRadio::ChannelId;
using NetRadio::Protocol::MsgProgramListEntry;
using NetRadio::Protocol::MsgProgramList;


static pthread_t tidList;
// 节目单包含的节目数量
static int nr_list_ent;
// 节目单信息数组，每一条存储一个节目频道信息
static struct NetRadio::Server::MediaLib::MediaLibEntry* list_ent;


static void* threadList(void* p) {
    size_t totalSize = sizeof( ChannelId );
    for (int i = 0; i < nr_list_ent; ++i) {
        totalSize += sizeof( struct MsgProgramListEntry ) + strlen( list_ent[i].description );
    }
    struct MsgProgramListEntry* ptrMsgProgramListEntry;
    struct MsgProgramList* ptrMsgProgramList;
    void* pVoid = malloc( totalSize );
    ptrMsgProgramList = static_cast<MsgProgramList*>(pVoid);
    if (ptrMsgProgramList == nullptr) {
        syslog( LOG_ERR, "malloc(): %s.", strerror(errno));
        exit( 1 );
    }


    ptrMsgProgramList->channelId = NetRadio::PROGRAM_LIST_CHANNEL_ID;
    ptrMsgProgramListEntry = ptrMsgProgramList->entry;

    for (int i = 0; i < nr_list_ent; ++i) {
        int size = sizeof( struct MsgProgramListEntry ) + strlen( list_ent[i].description );
        ptrMsgProgramListEntry->channelId = list_ent[i].channelId;
        ptrMsgProgramListEntry->len = htons( size );
        strcpy((char*) ptrMsgProgramListEntry->description, list_ent[i].description );
        // TODO 错误: !!! 这里的强转看不懂。
//        ptrMsgProgramListEntry = (((void*) ((char*) ptrMsgProgramListEntry)) + (void*) size);
//        ptrMsgProgramListEntry = ((char*) ptrMsgProgramListEntry) + (char*) size);
//        ptrMsgProgramListEntry = static_cast<MsgProgramListEntry*>((void*) (((char*) ptrMsgProgramListEntry) + size));
        ptrMsgProgramListEntry = (MsgProgramListEntry*) ((void*) (((char*) ptrMsgProgramListEntry) + size));
    }

    while (true) {
        ssize_t ret = sendto( socketFd, ptrMsgProgramList, totalSize, 0,
                              (sockaddr*) &senderAddress,
                              sizeof( senderAddress ));
        if (ret < 0) {
            syslog( LOG_WARNING, "sendto(NetRadio::Server::socketFd, ptrMsgProgramList, , , , ): %s",
                    strerror(errno));
        } else {
            syslog( LOG_DEBUG, "sendto(NetRadio::Server::socketFd, ptrMsgProgramList, , , , ): succeed." );
        }
        sleep( 1 );

    }
}


int NetRadio::Server::ThreadList::
threadListCreate(NetRadio::Server::MediaLib::MediaLibEntry* ptrMediaLibEntry, int nr_ent) {
    list_ent = ptrMediaLibEntry;
    nr_list_ent = nr_ent;

    int err = pthread_create( &tidList, nullptr, threadList, nullptr );
    if (err) {
        syslog( LOG_ERR, "pthread_create(): %s.", strerror( err ));
        return -1;
    }


    return 0;
}

int NetRadio::Server::ThreadList::
threadListDestroy() {
    pthread_cancel( tidList );
    pthread_join( tidList, nullptr );
    return 0;
}
